/**
 * 
 */
package gek.uni.aspirant.uml.utils.wizzards;

import gek.uni.aspirant.uml.utils.Messages;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.uml2.uml.Element;

/**
 * @author Gek
 * 
 */
public class SelectUmlElementWizard extends Wizard {

  private Element umlContext;
  private List<String> expressions;

  IWizardPage selectUmlContextPage = new SelectUmlContextElementWizardPage(
      Messages.SELECT_MODEL_ELEMENT);
  IWizardPage selectOclExpressionPage = new SelectOclExpressionWizardPage();

  /*
   * (non-Javadoc)
   * 
   * @see org.eclipse.jface.wizard.Wizard#performFinish()
   */
  @Override
  public boolean performFinish() {
    Object obj = ((SelectUmlContextElementWizardPage) selectUmlContextPage)
        .getUmlElement();
    if (obj instanceof Element)
      umlContext = (Element) obj;

    String oclCodeString = ((SelectOclExpressionWizardPage) selectOclExpressionPage)
        .getOclCodeString();
    String clearCode = removeOclComments(oclCodeString);
    expressions = findInvariants(clearCode, 0, false);

    return true;
  }

  @Override
  public void addPages() {
    super.addPages();
    addPage(selectUmlContextPage);
    addPage(selectOclExpressionPage);
  }

  public Element getUmlContext() {
    return umlContext;
  }

  public List<String> getExpressions() {
    return expressions;
  }

  private String removeOclComments(String oclBody) {
    String[] splits = oclBody.split("\n");
    StringBuilder bldr = new StringBuilder();
    for (String line : splits) {
      bldr.append(line.replaceAll("--.*", ""));
    }
    return bldr.toString();
  }

  /**
   * 
   * @param oclCode
   * @param startWithExpression
   *          - флаг, показывающий, что спецификатор "inv:" уже найден и
   *          необходимо определить конец ocl выражения
   * @return список ocl-выражений составляющих инвариант или null, если таковых
   *         нет
   */
  private List<String> findInvariants(String oclCode, int startIndex,
      boolean startWithExpression) {
    List<String> result = null;
    if (startWithExpression == false) {
      int invariantStart = oclCode.indexOf("inv", startIndex);
      if (invariantStart == -1)
        return null;
      invariantStart = oclCode.indexOf(":", invariantStart) + 1;
      result = findInvariants(oclCode, invariantStart, true);
    } else {
      int min = oclCode.indexOf("inv", startIndex);
      int another = oclCode.indexOf("pre", startIndex);
      if (min > another)
        min = another;

      another = oclCode.indexOf("post", startIndex);
      if (min > another)
        min = another;

      another = oclCode.indexOf("context", startIndex);
      if (min > another)
        min = another;

      if (min == -1)
        min = oclCode.length();
      String expressionCode = oclCode.substring(startIndex, min);
      String withoutNL = expressionCode.replaceAll("\n", "");
      result = new ArrayList<String>();
      result.add(withoutNL);

      List<String> moreInvariants = findInvariants(oclCode, min, false);
      if (moreInvariants != null)
        result.addAll(moreInvariants);
    }
    return result;
  }
}
